package main

import "fmt"

const BALLOT int = 10 //总的选票数量

type person struct {
	id     int    //学号id
	name   string //姓名
	ballot int    //得选票数
}

func main() {
	start()

}

func start() {

	//列出候选人、人名、票数、id
	pns := getPersonList()

	//构造一个map用于 可多轮投票    key:id,   value: person
	pnsMap := make(map[int]*person)
	for i:=0; i<len(pns); i++ {
		pnsMap[pns[i].id] = pns[i]
	}

	//listPersonMap(pnsMap)

	listPerson(pns)

	for len(pnsMap) > 1 {

		//投票
		vote(pnsMap)

		//结束投票
		//计算投票结果		//排序
		sortPersons(pns)
		listPerson(pns)


		if pns[0].ballot != pns[1].ballot {
			//投票结束
			//投票结果：列出候选人id， 姓名， 得票
			//得票胜出者
			fmt.Printf("投票最终结果，%s同学，最终以%d票当选班长!\n", pns[0].name, pns[0].ballot)
			break

		} else {
			//获取最高票 同票的人
			getVotedPerson(pns, pnsMap)
			fmt.Printf("有%d人并列获得最高票：%d， 再来一轮投票了\n", len(pnsMap), pns[0].ballot)
		}

	}


}



/**
投票
 */
func vote(pnsMap map[int]*person) {
	//循环投票 有20个选票可投
	fmt.Println("\n~~~~~~开始投票~~~~~~~~~~")
	listPersonMap(pnsMap)

loop:
	for i := 0; i < BALLOT; i++ {
		var choose int = -1
		//提示输入 投票
		fmt.Print("请输入班长候选人代号(数字0结束):")

		fmt.Scanln(&choose)

		pn, ok := pnsMap[choose]

		//0 结束投票
		switch {
		case choose == 0:
			break loop
		case ok: //学号id之内 为有效投票，计入投票数
			pn.ballot++
		default:
			fmt.Println("此选票无效，请输入正确的候选人代号！") //学号id之外为无效投票
			continue
		}

	}
}


/**
获取最高票 同票的人
 */
func getVotedPerson(pns[]*person, pnsMap map[int]*person) map[int]*person{

	for i:=1; i<len(pns); i++ {
		if pns[0].ballot != pns[i].ballot   {
			delete(pnsMap, pns[i].id)	//只留下 需要用于投票的
		}
	}

	return pnsMap
}

/*
把候选名单 按得选票数量排序
*/
func sortPersons(pns []*person) {

	for i := 0; i < len(pns)-1; i++ {
		for j := 0; j < len(pns)-i-1; j++ {

			if pns[j].ballot < pns[j+1].ballot {
				pns[j], pns[j+1] = pns[j+1], pns[j]
			}
		}
	}

}

/*
获取获选人名单
 */
func getPersonList() []*person {
	names := [...]string{"张三", "李四", "王五", "赵六", "田七"}

	personList := make([]*person, 0, len(names))

	for i := 0; i < len(names); i++ {
		pn := person{id: i + 1, name: names[i]}
		personList = append(personList, &pn)
	}

	return personList
}

/**
列出所有名单
 */
func listPerson(pnlist []*person) {
	if pnlist == nil || len(pnlist) == 0 {
		return
	}

	fmt.Println("\n======所有候选人===============")
	fmt.Println("代号\t姓名\t得票")

	for _, v := range pnlist {
		fmt.Printf("%d:\t%s\t[%d]\n", v.id, v.name, v.ballot)
	}
}

/**
列出待选名单
*/
func listPersonMap(pnsMap map[int]*person)  {
	fmt.Println("代号\t姓名\t得票")
	for _,v:=range pnsMap{
		fmt.Printf("%d:\t%s\t[%d]\n", v.id, v.name, v.ballot)
	}
}